package org.jeecg.access.platform.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.access.constant.PlatformType;
import org.jeecg.access.entity.PlatformAccount;
import org.jeecg.access.platform.entity.BaseUserInfo;
import org.jeecg.access.platform.entity.BaseWorkData;
import org.jeecg.access.platform.entity.KsUserInfo;
import org.jeecg.access.platform.entity.KsWorkData;
import org.jeecg.access.platform.mapper.KsUserInfoMapper;
import org.jeecg.access.platform.mapper.KsWorksDataMapper;
import org.jeecg.access.platform.service.PlatformHandler;
import org.jeecg.access.platform.util.HttpRequestUtil;
import org.jeecg.access.platform.util.JsonParserUtils;
import org.jeecg.access.service.PlatformAccountService;
import org.jeecg.common.util.UUIDGenerator;
import org.jeecg.util.DateTimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 快手数据获取服务实现类
 * 统一使用JsonParserUtils解析JSON，移除Map反序列化、JsonNode和ApiDataUtil/JsonUtil依赖
 */
@Slf4j
@Service
public class KsGetDataServiceImpl extends AbstractGetDataServiceImpl implements PlatformHandler {

    private final KsUserInfoMapper userInfoMapper;

    private final KsWorksDataMapper worksDataMapper;

    private final PlatformAccountService platformAccountService;

    @Value("${more.token}")
    private String token;
    @Value("${more.ks.userData}")
    private String userDataUrl;
    @Value("${more.ks.userPost}")
    private String userPostUrl;
    @Value("${batch.size:100}")
    private int userBatchSize;
    @Value("${works.batch.size:500}")
    private int worksBatchSize;

    /**
     * 构造方法：注入依赖并调用父类构造
     */
    @Autowired
    public KsGetDataServiceImpl(
            KsUserInfoMapper userInfoMapper,
            KsWorksDataMapper worksDataMapper,
            HttpRequestUtil httpRequestUtil,
            ObjectMapper objectMapper,
            PlatformAccountService platformAccountService
    ) {
        super(httpRequestUtil, objectMapper);
        this.userInfoMapper = userInfoMapper;
        this.worksDataMapper = worksDataMapper;
        this.platformAccountService = platformAccountService;
    }

    // ========================== 用户信息同步实现 ==========================

    /**
     * 获取快手用户列表
     */
    @Override
    protected List<? extends BaseUserInfo> fetchUserInfoList() {
        List<KsUserInfo> userInfos = userInfoMapper.getUserInfos();
        return userInfos != null ? userInfos : new ArrayList<>();
    }

    /**
     * 为单个用户创建请求头
     */
    @Override
    protected Map<String, String> createUserRequestHeaders(BaseUserInfo user) {
        Map<String, String> headers = new HashMap<>(2);
        headers.put("Content-Type", "application/json");
        headers.put("Authorization", token);
        return headers;
    }

    /**
     * 为单个用户组装请求报文
     */
    @Override
    protected String buildUserRequestData(BaseUserInfo user) {
        if (!(user instanceof KsUserInfo)) {
            log.error("用户类型错误，无法构建请求报文");
            return null;
        }
        KsUserInfo ksUser = (KsUserInfo) user;

        Map<String, Object> requestBody = new HashMap<>(2);
        requestBody.put("share_text", ksUser.getShareText());
        requestBody.put("proxy", "");

        try {
            return objectMapper.writeValueAsString(requestBody);
        } catch (JsonProcessingException e) {
            log.error("序列化用户请求参数失败", e);
            return null;
        }
    }

    /**
     * 获取用户信息API的URL
     */
    @Override
    protected String getUserApiUrl(BaseUserInfo user) {
        return userDataUrl;
    }

    /**
     * 获取用户信息的请求方法
     */
    @Override
    protected String getUserRequestMethod() {
        return "POST";
    }

    /**
     * 创建用户信息请求的重试决策器（增强版）
     * 校验逻辑：
     * 1. HTTP状态码为5xx时重试
     * 2. 响应为空或非JSON格式时重试
     * 3. 核心数据节点（data.profile、data.ownerCount）无效时重试
     */
    @Override
    protected HttpRequestUtil.RetryDecision createUserRetryDecision(BaseUserInfo user) {
        return new KsUserRetryDecision();
    }

    /**
     * 快手用户信息重试决策器
     */
    private class KsUserRetryDecision implements HttpRequestUtil.RetryDecision {
        @Override
        public boolean needRetry(int responseCode, String response) {
            // 1. HTTP状态码校验（5xx错误重试）
            if (responseCode >= 500 && responseCode < 600) {
                log.debug("用户请求HTTP 5xx错误({})，需要重试", responseCode);
                return true;
            }

            // 2. 响应为空或非JSON校验
            if (response == null || response.trim().isEmpty()) {
                log.debug("用户请求响应为空，需要重试");
                return true;
            }
            if (response.contains("<html>") || response.contains("<body>")) {
                log.debug("用户请求返回HTML内容（非JSON），需要重试");
                return true;
            }

            // 3. 核心数据节点校验
            try {
                // 校验业务状态
                Boolean isBusinessSuccess = JsonParserUtils.isSuccess(response);
                if (isBusinessSuccess == null || !isBusinessSuccess) {
                    log.debug("用户请求业务响应失败，需要重试");
                    return true;
                }

                // 校验核心节点
                Boolean isDataValid = JsonParserUtils.isNodeValid(response, "data");
                if (isDataValid == null || !isDataValid) {
                    log.debug("用户请求缺少data节点，需要重试");
                    return true;
                }

                // 校验后续解析需要的子节点
                Boolean isProfileValid = JsonParserUtils.isNodeValid(response, "data.profile");
                Boolean isOwnerCountValid = JsonParserUtils.isNodeValid(response, "data.ownerCount");
                if ((isProfileValid == null || !isProfileValid) || (isOwnerCountValid == null || !isOwnerCountValid)) {
                    log.debug("用户请求缺少data.profile或data.ownerCount节点，需要重试");
                    return true;
                }
            } catch (Exception e) {
                log.error("解析用户响应失败，需要重试", e);
                return true;
            }

            return false;
        }
    }

    /**
     * 从响应报文中解析数据并组装用户信息
     */
    @Override
    protected BaseUserInfo parseUserResponse(BaseUserInfo originalUser, String response) {
        if (!(originalUser instanceof KsUserInfo)) {
            log.error("用户类型错误，无法解析响应数据");
            return null;
        }
        KsUserInfo ksUser = (KsUserInfo) originalUser;

        try {
            // 检查核心节点有效性（依赖重试决策器，但二次校验确保安全）
            Boolean isDataValid = JsonParserUtils.isNodeValid(response, "data");
            if (isDataValid == null || !isDataValid) {
                log.error("用户信息响应缺少data节点");
                return null;
            }

            // 解析用户基础信息（直接通过路径提取）
            ksUser.setEid(JsonParserUtils.getStringValueFromString(response, "data.profile.eid"));
            ksUser.setName(JsonParserUtils.getStringValueFromString(response, "data.profile.user_name"));
            ksUser.setUserText(JsonParserUtils.getStringValueFromString(response, "data.profile.user_text"));
            ksUser.setUserId(JsonParserUtils.getStringValueFromString(response, "data.profile.user_id"));
            ksUser.setKwaiId(JsonParserUtils.getStringValueFromString(response, "data.profile.kwaiId"));

            // 解析认证信息
            ksUser.setDescription(JsonParserUtils.getStringValueFromString(response, "data.profile.verifiedDetail.description"));

            // 解析计数信息
            ksUser.setFan(JsonParserUtils.getIntValueFromString(response, "data.ownerCount.fan"));
            ksUser.setPhoto(JsonParserUtils.getIntValueFromString(response, "data.ownerCount.photo"));
            ksUser.setFollow(JsonParserUtils.getIntValueFromString(response, "data.ownerCount.follow"));
            ksUser.setPhotoPublic(JsonParserUtils.getIntValueFromString(response, "data.ownerCount.photo_public"));
            ksUser.setPhotoPrivate(JsonParserUtils.getIntValueFromString(response, "data.ownerCount.photo_private"));

            return ksUser;
        } catch (Exception e) {
            log.error("解析用户响应数据失败", e);
            return null;
        }
    }

    /**
     * 批量更新用户信息
     */
    @Override
    protected void batchUpdateUserInfo(List<? extends BaseUserInfo> userInfos) {
        if (userInfos.isEmpty()) {
            log.info("没有需要更新的快手用户信息");
            return;
        }

        List<KsUserInfo> ksUsers = new ArrayList<>(userInfos.size());
        for (int i = 0; i < userInfos.size(); i++) {
            BaseUserInfo user = userInfos.get(i);
            if (user instanceof KsUserInfo) {
                ksUsers.add((KsUserInfo) user);
            } else {
                log.warn("跳过非快手用户类型的数据，索引：{}", i);
            }
        }

        if (!ksUsers.isEmpty()) {
            // 分批处理，避免批量过大
            for (int i = 0; i < ksUsers.size(); i += userBatchSize) {
                int end = Math.min(i + userBatchSize, ksUsers.size());
                List<KsUserInfo> batch = new ArrayList<>();
                for (int j = i; j < end; j++) {
                    batch.add(ksUsers.get(j));
                }
                userInfoMapper.batchUpSert(batch);
                log.info("批量更新快手用户信息，批次 {} - {}，共 {} 条", i, end - 1, batch.size());
            }
            log.info("批量更新快手用户信息完成，总计 {} 条", ksUsers.size());
        }
    }

    // ========================== 作品数据同步实现 ==========================

    /**
     * 创建作品数据请求的重试决策器（增强版）
     */
    @Override
    protected HttpRequestUtil.RetryDecision createWorkRetryDecision(BaseWorkData workData) {
        return new KsWorkRetryDecision();
    }

    /**
     * 快手作品重试决策器
     */
    private class KsWorkRetryDecision implements HttpRequestUtil.RetryDecision {
        @Override
        public boolean needRetry(int responseCode, String response) {
            // 1. HTTP状态码校验（5xx错误重试）
            if (responseCode >= 500 && responseCode < 600) {
                log.debug("作品请求HTTP 5xx错误({})，需要重试", responseCode);
                return true;
            }

            // 2. 响应为空或非JSON校验
            if (response == null || response.trim().isEmpty()) {
                log.debug("作品请求响应为空，需要重试");
                return true;
            }
            if (response.contains("<html>") || response.contains("<body>")) {
                log.debug("作品请求返回HTML内容（非JSON），需要重试");
                return true;
            }

            // 3. 核心数据节点校验
            try {
                // 检查业务状态
                Boolean isBusinessSuccess = JsonParserUtils.isSuccess(response);
                if (isBusinessSuccess == null || !isBusinessSuccess) {
                    log.debug("作品请求业务响应失败，需要重试");
                    return true;
                }

                // 检查data节点有效性
                Boolean isDataValid = JsonParserUtils.isNodeValid(response, "data");
                if (isDataValid == null || !isDataValid) {
                    log.debug("作品请求缺少data节点，需要重试");
                    return true;
                }

                // 检查作品列表节点（data.feeds）是否为非空数组
                Integer feedsLength = JsonParserUtils.getListLength(response, "data.feeds");
                if (feedsLength == null || feedsLength <= 0) {
                    log.debug("作品请求核心节点data.feeds无效，需要重试");
                    return true;
                }
            } catch (Exception e) {
                log.error("解析作品响应失败，需要重试", e);
                return true;
            }

            return false;
        }
    }

    /**
     * 获取用户的所有作品（适配父类参数和重试逻辑）
     */
    @Override
    protected List<? extends BaseWorkData> fetchUserAllWorks(BaseUserInfo userInfo, String nowTime,Integer dataNum) throws Exception {
        if (!(userInfo instanceof KsUserInfo)) {
            log.error("用户类型错误，无法获取快手作品");
            return new ArrayList<>();
        }
        KsUserInfo ksUser = (KsUserInfo) userInfo;
        Map<String, String> headers = createHeaders(userInfo);

        return fetchUserWorks(ksUser, headers, nowTime);
    }

    /**
     * 批量更新作品数据
     */
    @Override
    protected void batchUpdateWorksData(List<? extends BaseWorkData> worksData) {
        if (worksData.isEmpty()) {
            log.info("没有需要更新的快手作品数据");
            return;
        }

        List<KsWorkData> ksWorks = new ArrayList<>(worksData.size());
        for (int i = 0; i < worksData.size(); i++) {
            BaseWorkData work = worksData.get(i);
            if (work instanceof KsWorkData) {
                ksWorks.add((KsWorkData) work);
            } else {
                log.warn("跳过非快手作品类型的数据，索引：{}", i);
            }
        }

        if (!ksWorks.isEmpty()) {
            // 分批处理，避免批量过大
            for (int i = 0; i < ksWorks.size(); i += worksBatchSize) {
                int end = Math.min(i + worksBatchSize, ksWorks.size());
                List<KsWorkData> batch = new ArrayList<>();
                for (int j = i; j < end; j++) {
                    batch.add(ksWorks.get(j));
                }
                worksDataMapper.batchUpSert(batch);
                log.info("批量更新快手作品数据，批次 {} - {}，共 {} 条", i, end - 1, batch.size());
            }
            log.info("批量更新快手作品数据完成，总计 {} 条", ksWorks.size());
        }
    }

    /**
     * 构造作品相关API的请求头
     */
    @Override
    protected Map<String, String> createHeaders(BaseUserInfo userInfo) {
        Map<String, String> headers = new HashMap<>(2);
        headers.put("Content-Type", "application/json");
        headers.put("Authorization", token);
        return headers;
    }

    // ========================== 自定义业务方法（适配优化） ==========================

    /**
     * 获取用户作品列表（使用增强的重试决策器）
     */
    private List<KsWorkData> fetchUserWorks(KsUserInfo user, Map<String, String> headers, String nowTime) throws IOException {
        String shareText = user.getShareText();
        if (shareText == null || shareText.isEmpty()) {
            log.warn("用户shareText为空，无法获取作品");
            return new ArrayList<>();
        }

        Map<String, Object> requestBody = new HashMap<>(2);
        requestBody.put("share_text", shareText);
        requestBody.put("proxy", "");

        String requestJson;
        try {
            requestJson = objectMapper.writeValueAsString(requestBody);
        } catch (JsonProcessingException e) {
            throw new IOException("序列化作品请求参数失败", e);
        }

        // 使用作品重试决策器（增强版）
        String response = httpRequestUtil.sendRequest(
                userPostUrl,
                "POST",
                headers,
                requestJson,
                createWorkRetryDecision(new KsWorkData())
        );

        if (response == null || response.trim().isEmpty()) {
            log.warn("获取用户 {} 作品响应为空", shareText);
            return new ArrayList<>();
        }

        return parseWorksResponse(response, user.getId(), shareText, nowTime);
    }

    /**
     * 解析作品响应数据（基于JsonParserUtils路径解析）
     */
    private List<KsWorkData> parseWorksResponse(String response, String userId, String shareText, String nowTime) {
        List<KsWorkData> worksList = new ArrayList<>();

        try {
            // 获取作品列表长度
            Integer feedsLength = JsonParserUtils.getListLength(response, "data.feeds");
            if (feedsLength == null || feedsLength <= 0) {
                log.info("快手用户 {} 没有作品数据", shareText);
                return worksList;
            }

            // 循环解析每个作品
            for (int i = 0; i < feedsLength; i++) {
                String basePath = "data.feeds[" + i + "]";
                try {
                    // 获取作品唯一标识
                    String photoId = JsonParserUtils.getStringValueFromString(response, basePath + ".photoId");
                    if (photoId == null || photoId.isEmpty()) {
                        log.warn("第{}个作品缺少photoId，跳过解析", i + 1);
                        continue;
                    }

                    KsWorkData work = new KsWorkData();
                    work.setId(UUIDGenerator.generate());
                    work.setUserId(userId);
                    work.setUpdateTime(nowTime);
                    work.setPhotoId(photoId);

                    // 基础信息解析
                    work.setCaption(JsonParserUtils.getStringValueFromString(response, basePath + ".caption"));

                    // 时间解析
                    Long timestamp = JsonParserUtils.getLongValueFromString(response, basePath + ".timestamp");
                    if (timestamp != null && timestamp > 0) {
                        work.setCreateTime(DateTimeUtil.convertMillisTimestamp(timestamp));
                    } else {
                        log.warn("作品 {} 的timestamp为空或无效", photoId);
                        work.setCreateTime(null);
                    }

                    // 统计信息解析
                    work.setLikeCount(JsonParserUtils.getIntValueFromString(response, basePath + ".likeCount"));
                    work.setCommentCount(JsonParserUtils.getIntValueFromString(response, basePath + ".commentCount"));
                    work.setViewCount(JsonParserUtils.getIntValueFromString(response, basePath + ".viewCount"));
                    work.setForwardCount(JsonParserUtils.getIntValueFromString(response, basePath + ".forwardCount"));

                    worksList.add(work);
                } catch (Exception e) {
                    log.error("解析第{}个作品数据失败: shareText={}", i + 1, shareText, e);
                }
            }
        } catch (Exception e) {
            log.error("解析作品列表响应失败: shareText={}", shareText, e);
        }

        return worksList;
    }

    // ========================== PlatformHandler接口实现 ==========================

    /**
     * 返回快手平台类型编码
     */
    @Override
    public String getPlatformType() {
        return PlatformType.KWAI.getCode();
    }

    /**
     * 获取本地系统中已有的快手用户数据
     */
    @Override
    public List<?> fetchExternalData() {
        List<KsUserInfo> localUserList = userInfoMapper.getUserInfos();
        if (localUserList == null) {
            log.warn("本地快手用户表查询返回null，返回空列表");
            return new ArrayList<>();
        }
        log.info("从本地快手用户表获取到 {} 条已有数据", localUserList.size());
        return localUserList;
    }

    /**
     * 从本地用户数据中提取快手账号唯一标识
     */
    @Override
    public String extractAccountId(Object data) {
        if (data == null || !(data instanceof KsUserInfo)) {
            log.warn("本地用户数据格式无效，无法提取账号ID");
            return null;
        }
        KsUserInfo localUser = (KsUserInfo) data;
        return localUser.getId();
    }

    /**
     * 校验账号有效性（使用JsonParserUtils）
     */
    @Override
    public boolean verifyAccount(PlatformAccount account) {
        if (account == null || account.getShareUrl() == null || account.getShareUrl().trim().isEmpty()) {
            log.warn("待校验账号信息无效（ID为空）");
            return false;
        }

        String shareText = account.getShareUrl().trim();
        KsUserInfo userInfo = new KsUserInfo();
        userInfo.setShareText(shareText);

        Map<String, String> headers = createHeaders(userInfo);

        try {
            String requestBody = buildUserRequestData(userInfo);
            if (requestBody == null) {
                log.error("构建账号校验请求报文失败");
                return false;
            }

            // 使用用户重试决策器校验
            String response = httpRequestUtil.sendRequest(
                    getUserApiUrl(userInfo),
                    getUserRequestMethod(),
                    headers,
                    requestBody,
                    createUserRetryDecision(userInfo)
            );

            if (response == null || response.trim().isEmpty()) {
                log.warn("账号[{}]校验失败：响应为空", shareText);
                return false;
            }

            log.info("账号[{}]校验成功：在快手真实存在", shareText);
            return true;
        } catch (Exception e) {
            log.error("账号[{}]校验失败：快手API请求异常", shareText, e);
            return false;
        }
    }

    /**
     * 将校验通过的账号同步到本地快手用户表
     */
    @Override
    public void writeToExternalSystem(PlatformAccount account) {
        if (account == null || account.getShareUrl() == null || account.getShareUrl().trim().isEmpty()) {
            log.warn("待同步账号信息无效（ID为空）");
            return;
        }

        String shareText = account.getShareUrl().trim();
        String nowTime = DateTimeUtil.getCurrentTimestamp();
        KsUserInfo userInfo = new KsUserInfo();

        userInfo.setShareText(shareText);
        userInfo.setCreator(account.getCreator());
        userInfo.setCreateTime(account.getCreateTime());
        userInfo.setUpdater(account.getUpdater());
        userInfo.setUpdateTime(nowTime);
        userInfo.setState(account.getState());
        userInfo.setId(account.getId());

        userInfoMapper.insert(userInfo);
        log.info("账号[{}]已同步到本地快手用户表", shareText);
    }

    @Override
    public String verifyAddedAccount(PlatformAccount account) {
        if (null == account.getShareUrl() || account.getShareUrl().trim().isEmpty()) {
            return "快手账号的shareUrl不能为空，请确保从app获取";
        }
//        if (isEmpty(account.getAppSecret())) {
//            return "快手账号的appSecret不能为空";
//        }
//        if (isEmpty(account.getShareUrl())) {
//            return "快手账号的shareUrl不能为空，请确保从app获取";
//        }
        QueryWrapper<PlatformAccount> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("platform_type", account.getPlatformType());
        queryWrapper.eq("share_url",account.getShareUrl());

        int count = platformAccountService.count(queryWrapper);
        if (count > 0) {
            return "快手账号的shareUrl账号已存在";
        }

        return null;
    }
}
